#pragma once

#include "sync_helper.h"

template <typename TYPE>
class SyncQueue {
public:
    SyncQueue()
    : mWaits(0) {
    }

    virtual ~SyncQueue() {
    }

    size_t Enqueue(const TYPE& obj) {
        SmartLock al(mMutex);
        mList.push_back(obj);
        if (mWaits) {
            mCond.NotifyOne();
        }
        return mList.size();
    }

    bool Dequeue(TYPE& obj, int32_t msec) {
        SmartLock lock(mMutex);
        if (mList.empty()) {
            ++mWaits;
            mCond.WaitFor(lock, msec);
            --mWaits;
        }

        if (mList.empty())
            return false;

        obj = mList.front();
        mList.pop_front();
        return true;
    }

private:
    SyncQueue(const SyncQueue&);
    SyncQueue& operator =(const SyncQueue&);

protected:
    std::list<TYPE> mList;
    SyncMutex mMutex;
    SyncCond mCond;
    size_t mWaits;
};
